home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Source.bin / Spinner.java < prev    next >
Text File  |  1998-09-25  |  36KB  |  1,204 lines

  1. package symantec.itools.awt.util.spinner;
  2.  
  3.  
  4. import java.awt.*;
  5. import java.awt.event.*;
  6. import java.beans.PropertyChangeEvent;
  7. import java.beans.PropertyChangeListener;
  8. import java.beans.PropertyVetoException;
  9. import java.beans.VetoableChangeListener;
  10. import java.io.Serializable;
  11. import java.util.ResourceBundle;
  12. import symantec.itools.awt.Orientation;
  13. import symantec.itools.beans.*;
  14.  
  15.  
  16. //     01/29/97    TWB    Integrated changes from Macintosh
  17. //    01/30/97    RKM    Changed updateText to check if the text has changed, to avoid flicker
  18. //                    Also changed paint to first call updateText and removed ifdef MAC
  19. //    06/02/97    MSH Updated to Java 1.1
  20. //    06/03/97    LAB Polished update to Java 1.1.
  21. //                    Changed the package to symantec.itools.awt.util.spinner.
  22. //    07/18/97    LAB Added add/removeNotify to handle event listener registration.
  23. //                    Made sourceActionEvent protected instead of public.
  24. //  07/30/97    CAR Inner adaptor class implements java.io.Serializable
  25. //    09/02/97    RKM    Better code in updateText()
  26. //                    Added getEntryFieldText() as per request from newsgroup
  27. //  08/24/87    CAR hooked up actionlistener to textfield to listen for changes to the text
  28. //                  call updateText() from actionPerformed when textField's text changes
  29. //                  call invalidate/validate in setOrientation
  30. //  08/28/97    LAB    Made the spinner buttons disable and enable according to the value.  Implemented
  31. //                    getPreferredSize and getMinimumSize (Addresses Mac Bug #7518).  Changed the
  32. //                    property name strings in bound and constrained event messages to match the Bean
  33. //                    Spec naming conventions.
  34. //  09/11/97    LAB    Added listener registration code to setOrientation to remove and add our
  35. //                    listener to the newly created horizontal or vertical spin button panel.
  36. //                    Fixes a problem when you switched orientations and the spinner no longer
  37. //                    spun (Addresses Mac Bug#7822).
  38. //  10/05/97    LAB    Added mechanism for internally constrained properties to be validated
  39. //                    after the component is added to the form to avoid code-gen order specific
  40. //                    dependencies.
  41. //  10/06/97    LAB    Changed addNotify to call it's super after listeners are hooked up so
  42. //                    verifyContstrainedPropertyValues will be called after the listeners
  43. //                    are hooked up.  Changed order of calls in verifyContstrainedPropertyValues
  44. //                    method to reflect dependancy correctly.  Changed setMax, setMin, and
  45. //                    setCurrent to set the temp values to the current values when changing the
  46. //                    current values.  Changed getMax, getMin, and getCurrent to return the temp
  47. //                    values if the component is not added. This fixes a problem at design time
  48. //                    where the component would revert to it's default state after a back run.
  49. //  10/12/97    LAB    Changed doLayout so if the component is sized smaller than the preferred
  50. //                    size for the textfield and buttons, the textfield is shortened (Addresses
  51. //                    Mac Bug #9051).  When the textField fires an action event, the focus is
  52. //                    now requested by the Spinner (this takes the focus away from the textField).
  53. //                    Rearranged addNotify to correctly add the action listener to the textField
  54. //                    (Addresses Mac Bug #9200).
  55. //  02/05/98    DS  Re-write of GUI
  56. //  09/04/98    MSH Edit box now filters user input, #62836
  57. //  09/09/98    MSH Spinner can no longer be edited when editable is set to false, #56076
  58. //  09/25/98    MSH Edit box no longer obliterates value if return is hit, #64895
  59.  
  60. /**
  61.  * This abstract class is used to create spinners. A spinner is a component
  62.  * with two small direction buttons that lets the user scroll a list of
  63.  * predetermined values to select one, or possibly enter a new legal value.
  64.  * @see symantec.itools.awt.util.spinner.ListSpinner
  65.  * @see symantec.itools.awt.util.spinner.NumericSpinner
  66.  * @version 1.1, June 2, 1997
  67.  * @author Symantec
  68.  */
  69. public abstract class Spinner
  70.     extends    Panel
  71.     implements Orientation,
  72.                Serializable
  73. {
  74.     class Action
  75.         implements ActionListener,
  76.                    java.io.Serializable
  77.     {
  78.         public void actionPerformed(ActionEvent e)
  79.         {
  80.             if(e.getSource() instanceof TextField)
  81.             {
  82.                    if(((TextField)e.getSource()) == textFld)
  83.                    {
  84.                        if ( validateText() )
  85.                         current = (new Integer( textFld.getText() )).intValue();
  86.  
  87.                     //Take the focus away from the edit box
  88.                     updateText(false);
  89.                     requestFocus();
  90.                        return;
  91.                 }
  92.             }
  93.  
  94.             String cmdStr = "";
  95.             String actionCommand = e.getActionCommand();
  96.  
  97.             if(actionCommand.equals("Increment"))
  98.             {
  99.                 scrollUp();
  100.                 cmdStr = "ScrollUp";
  101.                 sourceActionEvent(cmdStr);
  102.             }
  103.             else if(actionCommand.equals("Decrement"))
  104.             {
  105.                 scrollDown();
  106.                 cmdStr = "ScrollDown";
  107.                 sourceActionEvent(cmdStr);
  108.             }
  109.         }
  110.     }
  111.  
  112.     /**
  113.      * This is the PropertyChangeEvent handling inner class for the constrained Current property.
  114.      * Handles vetoing Current values that are not valid.
  115.      */
  116.     class CurrentVeto
  117.         implements VetoableChangeListener,
  118.                    java.io.Serializable
  119.     {
  120.         /**
  121.          * This method gets called when an attempt to change the constrained Current property is made.
  122.          * Ensures the given Current value is valid for this component.
  123.          *
  124.          * @param     e a <code>PropertyChangeEvent</code> object describing the
  125.          *             event source and the property that has changed.
  126.          * @exception PropertyVetoException if the recipient wishes the property
  127.          *              change to be rolled back.
  128.          */
  129.         public void vetoableChange(PropertyChangeEvent e)
  130.             throws PropertyVetoException
  131.         {
  132.             int i = ((Integer)e.getNewValue()).intValue();
  133.  
  134.             if(!isValidCurrentValue(i))
  135.             {
  136.                 throw new PropertyVetoException(errors.getString("InvalidCurrentValue") + i, e);
  137.             }
  138.         }
  139.     }
  140.  
  141.     /**
  142.      * This is the PropertyChangeEvent handling inner class for the constrained Max property.
  143.      * Handles vetoing Max values that are not valid.
  144.      */
  145.     class MaxVeto
  146.         implements VetoableChangeListener,
  147.                    Serializable
  148.     {
  149.         /**
  150.          * This method gets called when an attempt to change the constrained Current property is made.
  151.          * Ensures the given Max value is valid for this component.
  152.          *
  153.          * @param     e a <code>PropertyChangeEvent</code> object describing the
  154.          *             event source and the property that has changed.
  155.          * @exception PropertyVetoException if the recipient wishes the property
  156.          *              change to be rolled back.
  157.          */
  158.         public void vetoableChange(PropertyChangeEvent e)
  159.             throws PropertyVetoException
  160.         {
  161.             int i = ((Integer)e.getNewValue()).intValue();
  162.  
  163.             if(!isValidMaxValue(i))
  164.             {
  165.                 throw new PropertyVetoException(errors.getString("InvalidMaxValue") + i, e);
  166.             }
  167.         }
  168.     }
  169.  
  170.     /**
  171.      * This is the PropertyChangeEvent handling inner class for the constrained Min property.
  172.      * Handles vetoing Min values that are not valid.
  173.      */
  174.     class MinVeto
  175.         implements VetoableChangeListener,
  176.                    java.io.Serializable
  177.     {
  178.         /**
  179.          * This method gets called when an attempt to change the constrained Current property is made.
  180.          * Ensures the given Min value is valid for this component.
  181.          *
  182.          * @param     e a <code>PropertyChangeEvent</code> object describing the
  183.          *             event source and the property that has changed.
  184.          * @exception PropertyVetoException if the recipient wishes the property
  185.          *              change to be rolled back.
  186.          */
  187.         public void vetoableChange(PropertyChangeEvent e)
  188.             throws PropertyVetoException
  189.         {
  190.             int i = ((Integer)e.getNewValue()).intValue();
  191.  
  192.             if(!isValidMinValue(i))
  193.             {
  194.                 throw new PropertyVetoException(errors.getString("InvalidMinValue") + i, e);
  195.             }
  196.         }
  197.     }
  198.  
  199.     /**
  200.      * The default spinner orientation.
  201.      */
  202.     protected static int ORIENTATION_DEFAULT = ORIENTATION_VERTICAL;
  203.  
  204.     /**
  205.      * Reserved.
  206.      */
  207.     protected String                text;
  208.     /**
  209.      * Reserved.
  210.      */
  211.     protected int                   textWidth;
  212.     /**
  213.      * Reserved.
  214.      * @see #getOrientation
  215.      * @see #setOrientation
  216.      */
  217.     protected int                   orientation;
  218.     /**
  219.      * Whether the value can wrap from max to min, and from min to max.
  220.      * @see #isWrappable
  221.      * @see #setWrappable
  222.      */
  223.     protected boolean               wrappable;
  224.     /**
  225.      * Whether the Spinner's TextField is editable.
  226.      * @see #isEditable
  227.      * @see #setEditable
  228.      */
  229.     protected boolean               editable;
  230.     /**
  231.      * The minimum value the spinner may have.
  232.      * @see #getMin
  233.      * @see #setMin
  234.      */
  235.     protected int                   min;
  236.     /**
  237.      * The maximum value the spinner may have.
  238.      * @see #getMax
  239.      * @see #setMax
  240.      */
  241.     protected int                   max;
  242.     /**
  243.      * The current spinner value.
  244.      * @see #getCurrent
  245.      * @see #setCurrent
  246.      */
  247.     protected int                   current;
  248.     /**
  249.      * The amount the spinner's value is changed when scrolling step is taken.
  250.      * @see #scrollUp
  251.      * @see #scrollDown
  252.      */
  253.     protected int                   increment;
  254.     /**
  255.      * Tracks listeners for all vetoable property change events.
  256.      * @see #addVetoableChangeListener
  257.      * @see #removeVetoableChangeListener
  258.      */
  259.     protected VetoableChangeSupport vetos;
  260.     /**
  261.      * Tracks listeners for all property change events.
  262.      * @see #addPropertyChangeListener
  263.      * @see #removePropertyChangeListener
  264.      */
  265.     protected PropertyChangeSupport changes;
  266.     /**
  267.      * Error reporting strings.
  268.      */
  269.     protected ResourceBundle        errors;
  270.       /**
  271.      * The action listener which will receive action events
  272.      * from this component.
  273.      * @see #addActionListener
  274.      * @see #removeActionListener
  275.      */
  276.     protected ActionListener        actionListener;
  277.     /**
  278.      * A PropertyChangeEvent listener that constrains the "current" property as needed.
  279.      * @see #current
  280.      * @see #maxVeto
  281.      * @see #minVeto
  282.      */
  283.     protected CurrentVeto            currentVeto;
  284.     /**
  285.      * A PropertyChangeEvent listener that constrains the "max" property as needed.
  286.      * @see #max
  287.      * @see #currentVeto
  288.      * @see #minVeto
  289.      */
  290.     protected MaxVeto                maxVeto;
  291.     /**
  292.      * A PropertyChangeEvent listener that constrains the "min" property as needed.
  293.      * @see #min
  294.      * @see #currentVeto
  295.      * @see #maxVeto
  296.      */
  297.     protected MinVeto                minVeto;
  298.     /**
  299.      * An ActionEvent listener that handles typical spinner actions.
  300.      */
  301.     protected Action                action;
  302.     /**
  303.      * Tracks whether this component has been added to a container.
  304.      */
  305.     protected boolean               added;
  306.  
  307.     {
  308.         min       = 0;
  309.         max       = 0;
  310.         increment = 1;
  311.         current   = 0;
  312.         textWidth = 0;
  313.         vetos     = new VetoableChangeSupport(this);
  314.         changes   = new PropertyChangeSupport(this);
  315.         added     = false;
  316.     }
  317.  
  318.     /**
  319.      * Constructs a default spinner. The current value is 0,
  320.      * the minimum value is 0, the maximum value is 1, the increment is 1,
  321.      * it is not wrappable, and has a vertical orientation.
  322.      */
  323.     public Spinner()
  324.     {
  325.         //{{INIT_CONTROLS
  326.         GridBagLayout gridBagLayout;
  327.         gridBagLayout = new GridBagLayout();
  328.         super.setLayout(gridBagLayout);
  329.         setSize(61,20);
  330.         textFld = new java.awt.TextField();
  331.         textFld.setBounds(0,0,100,20);
  332.         GridBagConstraints gbc;
  333.         gbc = new GridBagConstraints();
  334.         gbc.gridx = 0;
  335.         gbc.gridy = 0;
  336.         gbc.weightx = 1.0;
  337.         gbc.weighty = 1.0;
  338.         gbc.fill = GridBagConstraints.HORIZONTAL;
  339.         gbc.insets = new Insets(0,0,0,0);
  340.         ((GridBagLayout)getLayout()).setConstraints(textFld, gbc);
  341.         add(textFld);
  342.         buttons = new symantec.itools.awt.util.spinner.SpinButtonPanel();
  343.         buttons.setLayout(new GridLayout(2,1,0,0));
  344.         buttons.setBounds(100,0,3,20);
  345.         gbc = new GridBagConstraints();
  346.         gbc.gridx = 1;
  347.         gbc.gridy = 0;
  348.         gbc.weightx = 0.05;
  349.         gbc.weighty = 1.0;
  350.         gbc.fill = GridBagConstraints.BOTH;
  351.         gbc.insets = new Insets(0,0,0,0);
  352.         ((GridBagLayout)getLayout()).setConstraints(buttons, gbc);
  353.         add(buttons);
  354.         //}}
  355.         textFld.setEditable(false);
  356.  
  357.         try
  358.         {
  359.             setWrappable(false);
  360.             setOrientation(ORIENTATION_DEFAULT);
  361.         }
  362.         catch(PropertyVetoException e)
  363.         {
  364.         }
  365.     }
  366.  
  367.     //{{DECLARE_CONTROLS
  368.     java.awt.TextField textFld;
  369.     symantec.itools.awt.util.spinner.SpinButtonPanel buttons;
  370.     //}}
  371.  
  372.     public void setEnabled( boolean f )
  373.     {
  374.         buttons.setEnabled( f );
  375.         textFld.setEnabled( f );
  376.     }
  377.  
  378.     /**
  379.      * Conditionally enables editing of the Spinner's TextField.
  380.      * @param f true = allow editing;
  381.      *          false = disallow editing
  382.      *
  383.      * @exception PropertyVetoException
  384.      * if the specified property value is unacceptable
  385.      */
  386.     public void setEditable(boolean f) throws PropertyVetoException
  387.     {
  388.         if(editable != f)
  389.         {
  390.             Boolean oldValue;
  391.             Boolean newValue;
  392.  
  393.             oldValue = new Boolean(editable);
  394.             newValue = new Boolean(f);
  395.             vetos.fireVetoableChange("editable", oldValue, newValue);
  396.             editable = f;
  397.             textFld.setEditable(editable);
  398.  
  399.             changes.firePropertyChange("editable", oldValue, newValue);
  400.         }
  401.     }
  402.  
  403.     /**
  404.      * @deprecated
  405.      * @see #isEditable
  406.      */
  407.     public boolean getEditable()
  408.     {
  409.         return editable;
  410.     }
  411.  
  412.     /**
  413.      * Returns whether the Spinner's TextField is editable.
  414.      * @return  <code>true</code> if the TextField can be edited,
  415.      *          <code>false</code> otherwise
  416.      * @see #setEditable
  417.      */
  418.     public boolean isEditable()
  419.     {
  420.         return editable;
  421.     }
  422.  
  423.     /**
  424.      * Sets whether the spinner buttons are laid out one above the other or
  425.      * one beside the other.
  426.      * @param o the new orientation, one of: ORIENTATION_VERTICAL, or ORIENTATION_HORIZONTAL
  427.      * @exception PropertyVetoException
  428.      * if the specified property value is unacceptable
  429.      * @see #getOrientation
  430.      * @see symantec.itools.awt.Orientation#ORIENTATION_VERTICAL
  431.      * @see symantec.itools.awt.Orientation#ORIENTATION_HORIZONTAL
  432.     */
  433.     public void setOrientation(int o)
  434.         throws PropertyVetoException
  435.     {
  436.         if(orientation != o)
  437.         {
  438.             Integer oldValue;
  439.             Integer newValue;
  440.  
  441.             oldValue = new Integer(orientation);
  442.             newValue = new Integer(o);
  443.             vetos.fireVetoableChange("orientation", oldValue, newValue);
  444.             orientation = o;
  445.             buttons.setOrientation(orientation);
  446.             changes.firePropertyChange("orientation", oldValue, newValue);
  447.         }
  448.     }
  449.  
  450.     /**
  451.      * Gets whether the spinner buttons are laid out one above the other or
  452.      * one beside the other.
  453.      * @return the orientation, one of: ORIENTATION_VERTICAL, or ORIENTATION_HORIZONTAL
  454.      * @see #setOrientation
  455.      * @see symantec.itools.awt.Orientation#ORIENTATION_VERTICAL
  456.      * @see symantec.itools.awt.Orientation#ORIENTATION_HORIZONTAL
  457.     */
  458.     public int getOrientation()
  459.     {
  460.         return (orientation);
  461.     }
  462.  
  463.     /**
  464.      * Sets whether the value can wrap from max to min, and from min to max.
  465.      * @param f <code>true</code> to allow the value to wrap
  466.      * @see #isWrappable
  467.      * @exception PropertyVetoException
  468.      * if the specified property value is unacceptable
  469.      */
  470.     public void setWrappable(boolean f)
  471.         throws PropertyVetoException
  472.     {
  473.         if(wrappable != f)
  474.         {
  475.             Boolean oldValue;
  476.             Boolean newValue;
  477.  
  478.             oldValue = new Boolean(wrappable);
  479.             newValue = new Boolean(f);
  480.             vetos.fireVetoableChange("wrappable", oldValue, newValue);
  481.             wrappable = f;
  482.             updateButtonStatus();
  483.             changes.firePropertyChange("wrappable", oldValue, newValue);
  484.         }
  485.     }
  486.  
  487.     /**
  488.      * @deprecated
  489.      * @see #isWrappable
  490.      */
  491.     public boolean getWrappable()
  492.     {
  493.         return (wrappable);
  494.     }
  495.  
  496.     /**
  497.      * Gets whether the value can wrap from max to min, and from min to max.
  498.      * @return <code>true</code> if the value is allowed to wrap
  499.      * @see #setWrappable
  500.      */
  501.     public boolean isWrappable()
  502.     {
  503.         return (wrappable);
  504.     }
  505.  
  506.     public Dimension getPreferredSize()
  507.     {
  508.         Dimension   textFldDim;
  509.         Dimension   btnsDim;
  510.  
  511.         textFldDim  = textFld.getPreferredSize();
  512.         btnsDim     = buttons.getPreferredSize();
  513.  
  514.         return (new Dimension(textFldDim.width + btnsDim.width, Math.max(textFldDim.height, btnsDim.height)));
  515.     }
  516.  
  517.     public Dimension getMinimumSize()
  518.     {
  519.         return (getPreferredSize());
  520.     }
  521.  
  522.     /**
  523.      * Sets the minimum value the spinner may have.
  524.      * @param i the new minimum value
  525.      * @see #getMin
  526.      *
  527.      * @exception PropertyVetoException
  528.      * if the specified property value is unacceptable
  529.      */
  530.     public void setMin(int i)
  531.         throws PropertyVetoException
  532.     {
  533.         if(min != i)
  534.         {
  535.             Integer oldValue;
  536.             Integer newValue;
  537.  
  538.             oldValue = new Integer(min);
  539.             newValue = new Integer(i);
  540.             vetos.fireVetoableChange("min", oldValue, newValue);
  541.             min = i;
  542.  
  543.             if(getCurrent() < min)
  544.             {
  545.                    setCurrent(min);
  546.             }
  547.             else
  548.             {
  549.                 updateButtonStatus();
  550.             }
  551.  
  552.             changes.firePropertyChange("min", oldValue, newValue);
  553.         }
  554.     }
  555.  
  556.     /**
  557.      * Gets the current minimum value the spinner may have.
  558.      * @return the current minimum value
  559.      * @see #setMin
  560.      */
  561.     public int getMin()
  562.     {
  563.         return (min);
  564.     }
  565.  
  566.     /**
  567.      * Sets the maximum value the spinner may have.
  568.      * @param i the new maximum value
  569.      * @see #getMax
  570.      *
  571.      * @exception PropertyVetoException
  572.      * if the specified property value is unacceptable
  573.      */
  574.     public void setMax(int i) throws PropertyVetoException
  575.     {
  576.         if(max != i)
  577.         {
  578.             Integer oldValue;
  579.             Integer newValue;
  580.  
  581.             oldValue = new Integer(max);
  582.             newValue = new Integer(i);
  583.             vetos.fireVetoableChange("max", oldValue, newValue);
  584.             max = i;
  585.  
  586.             if(getCurrent() > max)
  587.             {
  588.                 setCurrent(max);
  589.             }
  590.             else
  591.             {
  592.                 updateButtonStatus();
  593.             }
  594.  
  595.             changes.firePropertyChange("max", oldValue, newValue);
  596.         }
  597.     }
  598.  
  599.     /**
  600.      * Gets the current maximum value the spinner may have.
  601.      * @return the current maximum value
  602.      * @see #setMax
  603.      */
  604.     public int getMax()
  605.     {
  606.         return (max);
  607.     }
  608.  
  609.     /**
  610.      * Sets the value of the spinner.
  611.      * @param i the new value
  612.      * @see #getCurrent
  613.      *
  614.      * @exception PropertyVetoException
  615.      * if the specified property value is unacceptable
  616.      */
  617.     public void setCurrent(int i) throws PropertyVetoException
  618.     {
  619.         if(current != i)
  620.         {
  621.                Integer oldValue;
  622.             Integer newValue;
  623.  
  624.                oldValue = new Integer(current);
  625.             newValue = new Integer(i);
  626.             vetos.fireVetoableChange("current", oldValue, newValue);
  627.             current = i;
  628.             updateText(false);
  629.             updateButtonStatus();
  630.             changes.firePropertyChange("current", oldValue, newValue);
  631.         }
  632.     }
  633.  
  634.     /**
  635.      * Gets the current value of the spinner.
  636.      * @return the current spinner value
  637.      * @see #setCurrent
  638.      */
  639.     public int getCurrent()
  640.     {
  641.         if ( validateText() )
  642.         {
  643.             Integer i = new Integer( textFld.getText() );
  644.             current =  i.intValue();
  645.         }
  646.         return (current);
  647.     }
  648.  
  649.     /**
  650.      * Sets whether the spinner buttons will continually post notify events
  651.      * while pressed.
  652.      * @param f true = send messages; false = do not send messages
  653.      * @see #isNotifyWhilePressed
  654.      * @see #setDelay
  655.      * @see #getDelay
  656.      *
  657.      * @exception PropertyVetoException
  658.      * if the specified property value is unacceptable
  659.      */
  660.     public void setNotifyWhilePressed(boolean f)
  661.         throws PropertyVetoException
  662.     {
  663.         if(f != buttons.getNotifyWhilePressed())
  664.         {
  665.             Boolean oldValue;
  666.             Boolean newValue;
  667.  
  668.             oldValue = new Boolean(getNotifyWhilePressed());
  669.             newValue = new Boolean(f);
  670.             vetos.fireVetoableChange("notifyWhilePressed", oldValue, newValue);
  671.             buttons.setNotifyWhilePressed(f);
  672.             changes.firePropertyChange("notifyWhilePressed", oldValue, newValue);
  673.         }
  674.     }
  675.  
  676.     /**
  677.      * Gets the current notifyWhilePressed status.
  678.      * @return true if notify events posted while pressed, false otherwise
  679.      * @see #setNotifyWhilePressed
  680.      * @see #setDelay
  681.      * @see #getDelay
  682.      */
  683.     public boolean isNotifyWhilePressed()
  684.     {
  685.         return (buttons.isNotifyWhilePressed());
  686.     }
  687.  
  688.     /**
  689.      * @deprecated
  690.      * @see #isNotifyWhilePressed
  691.      */
  692.     public boolean getNotifyWhilePressed()
  693.     {
  694.         return isNotifyWhilePressed();
  695.     }
  696.  
  697.     /**
  698.      * Sets the notification event delay of the spinner buttons in milliseconds.
  699.      * @param d the delay between notification events in milliseconds
  700.      * @see #setNotifyWhilePressed
  701.      * @see #getDelay
  702.      *
  703.      * @exception PropertyVetoException
  704.      * if the specified property value is unacceptable
  705.      */
  706.     public void setDelay(int d) throws PropertyVetoException
  707.     {
  708.         if(d != buttons.getDelay())
  709.         {
  710.             Integer oldValue;
  711.             Integer newValue;
  712.  
  713.             oldValue = new Integer(buttons.getDelay());
  714.             newValue = new Integer(d);
  715.  
  716.             vetos.fireVetoableChange("delay", oldValue, newValue);
  717.             buttons.setDelay(d);
  718.             changes.firePropertyChange("delay", oldValue, newValue);
  719.         }
  720.     }
  721.  
  722.     /**
  723.      * Returns the current delay between notification events of the spinner
  724.      * buttons in milliseconds.
  725.      * @see #setNotifyWhilePressed
  726.      * @see #setDelay
  727.      */
  728.     public int getDelay()
  729.     {
  730.         return buttons.getDelay();
  731.     }
  732.  
  733.     /**
  734.      * Returns the text that is in the entry TextField.
  735.      */
  736.     public String getEntryFieldText()
  737.     {
  738.         return (textFld.getText());
  739.     }
  740.  
  741.     /**
  742.      * Takes no action.
  743.      * This is a standard Java AWT method which gets called to specify
  744.      * which layout manager should be used to layout the components in
  745.      * standard containers.
  746.      *
  747.      * Since layout managers CANNOT BE USED with this container the standard
  748.      * setLayout has been OVERRIDDEN for this container and does nothing.
  749.      *
  750.      * @param lm the layout manager to use to layout this container's components
  751.      * (IGNORED)
  752.      * @see java.awt.Container#getLayout
  753.      **/
  754.     public void setLayout(LayoutManager lm)
  755.     {
  756.     }
  757.  
  758.     /**
  759.      * Tells this component that it has been added to a container.
  760.      * This is a standard Java AWT method which gets called by the AWT when
  761.      * this component is added to a container. Typically, it is used to
  762.      * create this component's peer.
  763.      *
  764.      * It has been overridden here to hook-up event listeners.
  765.      * It is also used to setup the component, creating the TextField as needed.
  766.      *
  767.      * @see #removeNotify
  768.      */
  769.     public synchronized void addNotify()
  770.     {
  771.         super.addNotify();
  772.         added = true;
  773.         errors = ResourceBundle.getBundle("symantec.itools.resources.ErrorsBundle");
  774.  
  775.         //Hook up listeners
  776.         if(action == null)
  777.         {
  778.             action = new Action();
  779.             buttons.addActionListener(action);
  780.             textFld.addActionListener(action);
  781.         }
  782.  
  783.         if(currentVeto == null)
  784.         {
  785.             currentVeto = new CurrentVeto();
  786.             addCurrentListener(currentVeto);
  787.         }
  788.  
  789.         if(maxVeto == null)
  790.         {
  791.             maxVeto = new MaxVeto();
  792.             addMaxListener(maxVeto);
  793.         }
  794.  
  795.         if(minVeto == null)
  796.         {
  797.             minVeto = new MinVeto();
  798.             addMinListener(minVeto);
  799.         }
  800.  
  801.         updateText(true);
  802.     }
  803.  
  804.     /**
  805.      * Tells this component that it is being removed from a container.
  806.      * This is a standard Java AWT method which gets called by the AWT when
  807.      * this component is removed from a container. Typically, it is used to
  808.      * destroy the peers of this component and all its subcomponents.
  809.      *
  810.      * It has been overridden here to unhook event listeners.
  811.      *
  812.      * @see #addNotify
  813.      */
  814.     public synchronized void removeNotify()
  815.     {
  816.         //Unhook listeners
  817.         if(action != null)
  818.         {
  819.             textFld.removeActionListener(action);
  820.             buttons.removeActionListener(action);
  821.             action = null;
  822.         }
  823.  
  824.         if(currentVeto != null)
  825.         {
  826.             removeCurrentListener(currentVeto);
  827.             currentVeto = null;
  828.         }
  829.  
  830.         if(maxVeto != null)
  831.         {
  832.             removeMaxListener(maxVeto);
  833.             maxVeto = null;
  834.         }
  835.  
  836.         if(minVeto != null)
  837.         {
  838.             removeMinListener(minVeto);
  839.             minVeto = null;
  840.         }
  841.  
  842.         super.removeNotify();
  843.     }
  844.  
  845.       /**
  846.      * Adds the specified action listener to receive action events
  847.      * from this component.
  848.      * @param l the action listener
  849.      * @see #removeActionListener
  850.      */
  851.     public synchronized void addActionListener(ActionListener l)
  852.     {
  853.         actionListener = AWTEventMulticaster.add(actionListener, l);
  854.     }
  855.  
  856.     /**
  857.      * Removes the specified action listener so it no longer receives
  858.      * action events from this component.
  859.      * @param l the action listener
  860.      * @see #addActionListener
  861.      */
  862.     public synchronized void removeActionListener(ActionListener l)
  863.     {
  864.         actionListener = AWTEventMulticaster.remove(actionListener, l);
  865.     }
  866.  
  867.     /**
  868.      * Adds a listener for all property change events.
  869.      * @param listener the listener to add
  870.      * @see #removePropertyChangeListener
  871.      */
  872.     public synchronized void addPropertyChangeListener(PropertyChangeListener listener)
  873.     {
  874.         changes.addPropertyChangeListener(listener);
  875.     }
  876.  
  877.     /**
  878.      * Removes a listener for all property change events.
  879.      * @param listener the listener to remove
  880.      * @see #addPropertyChangeListener
  881.      */
  882.     public synchronized void removePropertyChangeListener(PropertyChangeListener listener)
  883.     {
  884.         changes.removePropertyChangeListener(listener);
  885.     }
  886.  
  887.     /**
  888.      * Adds a listener for all vetoable property change events.
  889.      * @param listener the listener to add
  890.      * @see #removeVetoableChangeListener
  891.      */
  892.     public synchronized void addVetoableChangeListener(VetoableChangeListener listener)
  893.     {
  894.         vetos.addVetoableChangeListener(listener);
  895.     }
  896.  
  897.     /**
  898.      * Removes a listener for all vetoable property change events.
  899.      * @param listener the listener to remove
  900.      * @see #addVetoableChangeListener
  901.      */
  902.     public synchronized void removeVetoableChangeListener(VetoableChangeListener listener)
  903.     {
  904.         vetos.removeVetoableChangeListener(listener);
  905.     }
  906.  
  907.     /**
  908.      * Adds a listener for the current property changes.
  909.      * @param listener the listener to add.
  910.      * @see #removeCurrentListener(java.beans.PropertyChangeListener)
  911.      */
  912.     public synchronized void addCurrentListener(PropertyChangeListener listener)
  913.     {
  914.         changes.addPropertyChangeListener("current", listener);
  915.     }
  916.  
  917.     /**
  918.      * Removes a listener for the current property changes.
  919.      * @param listener the listener to remove.
  920.      * @see #addCurrentListener(java.beans.PropertyChangeListener)
  921.      */
  922.     public synchronized void removeCurrentListener(PropertyChangeListener listener)
  923.     {
  924.         changes.removePropertyChangeListener("current", listener);
  925.     }
  926.  
  927.     /**
  928.      * Adds a vetoable listener for the current property changes.
  929.      * @param listener the listener to add.
  930.      * @see #removeCurrentListener(java.beans.VetoableChangeListener)
  931.      */
  932.     public synchronized void addCurrentListener(VetoableChangeListener listener)
  933.     {
  934.         vetos.addVetoableChangeListener("current", listener);
  935.     }
  936.  
  937.     /**
  938.      * Removes a vetoable listener for the current property changes.
  939.      * @param listener the listener to remove.
  940.      * @see #addCurrentListener(java.beans.VetoableChangeListener)
  941.      */
  942.     public synchronized void removeCurrentListener(VetoableChangeListener listener)
  943.     {
  944.         vetos.removeVetoableChangeListener("current", listener);
  945.     }
  946.  
  947.     /**
  948.      * Adds a listener for the max property changes.
  949.      * @param listener the listener to add.
  950.      * @see #removeMaxListener(java.beans.PropertyChangeListener)
  951.      */
  952.     public synchronized void addMaxListener(PropertyChangeListener listener)
  953.     {
  954.         changes.addPropertyChangeListener("max", listener);
  955.     }
  956.  
  957.     /**
  958.      * Removes a listener for the max property changes.
  959.      * @param listener the listener to remove.
  960.      * @see #addMaxListener(java.beans.PropertyChangeListener)
  961.      */
  962.     public synchronized void removeMaxListener(PropertyChangeListener listener)
  963.     {
  964.         changes.removePropertyChangeListener("max", listener);
  965.     }
  966.  
  967.     /**
  968.      * Adds a vetoable listener for the max property changes.
  969.      * @param listener the listener to add.
  970.      * @see #removeMaxListener(java.beans.VetoableChangeListener)
  971.      */
  972.     public synchronized void addMaxListener(VetoableChangeListener listener)
  973.     {
  974.         vetos.addVetoableChangeListener("max", listener);
  975.     }
  976.  
  977.     /**
  978.      * Removes a vetoable listener for the max property changes.
  979.      * @param listener the listener to remove.
  980.      * @see #addMaxListener(java.beans.VetoableChangeListener)
  981.      */
  982.     public synchronized void removeMaxListener(VetoableChangeListener listener)
  983.     {
  984.         vetos.removeVetoableChangeListener("max", listener);
  985.     }
  986.  
  987.     /**
  988.      * Adds a listener for the min property changes.
  989.      * @param listener the listener to add.
  990.      * @see #removeMinListener(java.beans.PropertyChangeListener)
  991.      */
  992.     public synchronized void addMinListener(PropertyChangeListener listener)
  993.     {
  994.         changes.addPropertyChangeListener("min", listener);
  995.     }
  996.  
  997.     /**
  998.      * Removes a listener for the min property changes.
  999.      * @param listener the listener to remove.
  1000.      * @see #addMinListener(java.beans.PropertyChangeListener)
  1001.      */
  1002.     public synchronized void removeMinListener(PropertyChangeListener listener)
  1003.     {
  1004.         changes.removePropertyChangeListener("min", listener);
  1005.     }
  1006.  
  1007.     /**
  1008.      * Adds a vetoable listener for the min property changes.
  1009.      * @param listener the listener to add.
  1010.      * @see #removeMinListener(java.beans.VetoableChangeListener)
  1011.      */
  1012.     public synchronized void addMinListener(VetoableChangeListener listener)
  1013.     {
  1014.         vetos.addVetoableChangeListener("min", listener);
  1015.     }
  1016.  
  1017.     /**
  1018.      * Removes a vetoable listener for the min property changes.
  1019.      * @param listener the listener to remove.
  1020.      * @see #addMinListener(java.beans.VetoableChangeListener)
  1021.      */
  1022.     public synchronized void removeMinListener(VetoableChangeListener listener)
  1023.     {
  1024.         vetos.removeVetoableChangeListener("min", listener);
  1025.     }
  1026.  
  1027.     /**
  1028.      * Is the given value valid for the Current property .
  1029.      * @param i the given value
  1030.      * @return true if the given value is acceptable, false if not.
  1031.      */
  1032.     protected boolean isValidCurrentValue(int i)
  1033.     {
  1034.         if (i > max || i < min)
  1035.             return false;
  1036.         else
  1037.             return true;
  1038.     }
  1039.  
  1040.     /**
  1041.      * Is the given value valid for the Max property .
  1042.      * @param i the given value
  1043.      * @return true if the given value is acceptable, false if not.
  1044.      */
  1045.     protected boolean isValidMaxValue(int i)
  1046.     {
  1047.         return (i >= min);
  1048.     }
  1049.  
  1050.     /**
  1051.      * Is the given value valid for the Min property .
  1052.      * @param i the given value
  1053.      * @return true if the given value is acceptable, false if not.
  1054.      */
  1055.     protected boolean isValidMinValue(int i)
  1056.     {
  1057.         return (i <= max);
  1058.     }
  1059.  
  1060.     /**
  1061.     * Fire an action event to the listeners
  1062.     */
  1063.     protected void sourceActionEvent( String s)
  1064.     {
  1065.         if (actionListener != null)
  1066.             actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, s));
  1067.     }
  1068.  
  1069.     /**
  1070.      * Increments the spinner's value and handles wrapping as needed.
  1071.      * @see #scrollDown
  1072.      * @see #increment
  1073.      */
  1074.     protected void scrollUp()
  1075.     {
  1076.         try
  1077.         {
  1078.             if ( validateText() )
  1079.             {
  1080.                 Integer i = new Integer( textFld.getText() );
  1081.                 current =  i.intValue();
  1082.             }
  1083.             setCurrent(current + increment);
  1084.         }
  1085.         catch (PropertyVetoException exc)
  1086.         {
  1087.             if(wrappable)
  1088.             {
  1089.                 try { setCurrent(min); } catch (PropertyVetoException ex) {}
  1090.             }
  1091.             else
  1092.             {
  1093.                 try { setCurrent(max); } catch (PropertyVetoException ex) {}
  1094.             }
  1095.         }
  1096.  
  1097.         updateText(false);
  1098.     }
  1099.  
  1100.     /**
  1101.      * Decrements the spinner's value and handles wrapping as needed.
  1102.      * @see #scrollUp
  1103.      * @see #increment
  1104.      */
  1105.     protected void scrollDown()
  1106.     {
  1107.         try
  1108.         {
  1109.             if ( validateText() )
  1110.             {
  1111.                 Integer i = new Integer( textFld.getText() );
  1112.                 current =  i.intValue();
  1113.             }
  1114.             setCurrent(current - increment);
  1115.         }
  1116.         catch (PropertyVetoException exc)
  1117.         {
  1118.             if (wrappable)
  1119.             {
  1120.                 try { setCurrent(max); } catch (PropertyVetoException exc1) {}
  1121.             }
  1122.             else
  1123.             {
  1124.                 try { setCurrent(min); } catch (PropertyVetoException exc1) {}
  1125.             }
  1126.         }
  1127.  
  1128.         updateText(false);
  1129.     }
  1130.  
  1131.     /**
  1132.      * Updates the text field with the current text, as needed or depending on the force flag.
  1133.      * @param force If true, causes the text field to update even if the value has not changed.
  1134.      * @see #getCurrentText
  1135.      */
  1136.     protected void updateText(boolean force)
  1137.     {
  1138.         String currentText;
  1139.  
  1140.         currentText = getCurrentText();
  1141.  
  1142.         //If the text has changed, put the new text into the text field
  1143.         if(force || !textFld.getText().equals(currentText))
  1144.         {
  1145.               textFld.setText(currentText);
  1146.         }
  1147.     }
  1148.  
  1149.     /**
  1150.      * Handles enabling or disabling the spinner buttons as needed.
  1151.      */
  1152.     protected void updateButtonStatus()
  1153.     {
  1154.         if(buttons != null)
  1155.         {
  1156.             if(wrappable)
  1157.             {
  1158.                 buttons.setUpButtonEnabled(true);
  1159.                 buttons.setDownButtonEnabled(true);
  1160.             }
  1161.             else
  1162.             {
  1163.                 if(current == max && current == min)
  1164.                 {
  1165.                     buttons.setUpButtonEnabled(false);
  1166.                     buttons.setDownButtonEnabled(false);
  1167.                 }
  1168.                 else if(current == max)
  1169.                 {
  1170.                     buttons.setUpButtonEnabled(false);
  1171.                     buttons.setDownButtonEnabled(true);
  1172.                 }
  1173.                 else if(current == min)
  1174.                 {
  1175.                     buttons.setUpButtonEnabled(true);
  1176.                     buttons.setDownButtonEnabled(false);
  1177.                 }
  1178.                 else
  1179.                 {
  1180.                     buttons.setUpButtonEnabled(true);
  1181.                     buttons.setDownButtonEnabled(true);
  1182.                 }
  1183.             }
  1184.         }
  1185.     }
  1186.  
  1187.     /**
  1188.      * Gets the currently selected string from the list.
  1189.      * @return the string currently visible in the Spinner
  1190.      * @see #updateText(boolean)
  1191.      */
  1192.     protected abstract String getCurrentText();
  1193.  
  1194.     /**
  1195.      * returns boolean if text in field is a valid entry
  1196.      * @return true if text is valid
  1197.      */
  1198.     protected boolean validateText( )
  1199.     {
  1200.         return false;
  1201.     }
  1202. }
  1203.  
  1204.